package com.jxtti.utils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.jxtti.dao.UserDao;
import com.jxtti.model.User;
import com.jxtti.service.UserService;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

/*
 *JiangJieBao
 *
 * */

@Component("cookieUtil")
public class CookieUtil {

	// 设置cookie有效期是两个星期，根据需要自定义
	private final static long cookieMaxAge = 60 * 60 * 24 * 7 * 2;
	
	//用户dao,实行和后台操作
	@Autowired
	private UserDao userDao;
	
	@Autowired
	private UserService userService; 
	
	/**
	 *保存Cookie到客户端
	 *在中被调用
	 *传递进来的userInfo对象中封装了在登陆时填写的用户名与密码
	 * @param userInfo
	 * @param response
	 */
	public void saveCookie(User userInfo,
			HttpServletResponse response) {

		// cookie的有效期
		long validTime = System.currentTimeMillis() + (cookieMaxAge * 1000);
		
		// MD5加密用户详细信息
		String cookieValueWithMd5 = getMD5(userInfo.getUserName() + ":"+ userInfo.getPassword() + ":" + validTime + ":" + Constants.WEB_KEY);
		
		// 将要被保存的完整的Cookie值
		String cookieValue = userInfo.getUserName() + ":" + validTime + ":"+ cookieValueWithMd5;
		
		// 再一次对Cookie的值进行BASE64编码
		String cookieValueBase64 = new String(Base64.encode(cookieValue.getBytes()));
		
		// 开始保存Cookie
		Cookie cookie = new Cookie(Constants.COOKIE_DOMAIN_NAME, cookieValueBase64);
		
		// 存两年(这个值应该大于或等于validTime)
		cookie.setMaxAge(60 * 60 * 24 * 365 * 2);
		// cookie有效路径是网站根目录
		cookie.setPath("/");
		// 向客户端写入
		response.addCookie(cookie);
	}
	/**
	 * 存储变量到cookie
	 * @param flag
	 * @param response
	 */
	public void saveCookieFlag(String flag,HttpServletResponse response) {
		
		Cookie cookie = new Cookie("reset", "1");
		// 存两年(这个值应该大于或等于validTime)
		cookie.setMaxAge(60 * 60 * 24 * 365 * 2);
		// cookie有效路径是网站根目录
		cookie.setPath("/");
		// 向客户端写入
		response.addCookie(cookie);
	}
	
	/**
	 * 读取变量
	 * @param request
	 * @param response
	 * @param flag:标志
	 * @return：1成功；-1失败。
	 */
	public long readCookieFlag(HttpServletRequest request,
			HttpServletResponse response,String flag){
		// 根据cookieName取cookieValue
				Cookie cookies[] = request.getCookies();
				String cookieValue = null;
				if (cookies != null) {
					for (int i = 0; i < cookies.length; i++) {
						if (flag.equals(cookies[i].getName())) {
							cookieValue = cookies[i].getValue();
							break;}
					}
				}
				// 如果cookieValue为空,返回,
				if (cookieValue == null) {
					return -1;
				}
		return 1;
	}

	/**
	 * 读取Cookie,自动完成登陆操作
	 * 在Filter程序中调用该方法,
	 * @param request
	 * @param response
	 * @param chain
	 * @throws IOException
	 * @throws ServletException
	 * @throws UnsupportedEncodingException
	 * 返回：
		用户id >1：完成
		-1：正常进入
		-2：非法登陆
		-3：Cookie已经失效
		-4：cookie验证错误
		-5：其它
	 */
	public long readCookieAndLogon(HttpServletRequest request,
			HttpServletResponse response)
			throws IOException, ServletException, UnsupportedEncodingException {
		// 根据cookieName取cookieValue
		Cookie cookies[] = request.getCookies();
		String cookieValue = null;
		if (cookies != null) {
			for (int i = 0; i < cookies.length; i++) {
				if (Constants.COOKIE_DOMAIN_NAME.equals(cookies[i].getName())) {
					cookieValue = cookies[i].getValue();
					break;
				}
			}
		}
		// 如果cookieValue为空,返回,
		if (cookieValue == null) {
			return -1;
		}
		// 如果cookieValue不为空,才执行下面的代码
		// 先得到的CookieValue进行Base64解码
		String cookieValueAfterDecode = new String(Base64.decode(cookieValue),"utf-8");
		// 对解码后的值进行分拆,得到一个数组,如果数组长度不为3,就是非法登陆
		String cookieValues[] = cookieValueAfterDecode.split(":");
		if (cookieValues.length != 3) {
			return -2;
		}
		// 判断是否在有效期内,过期就删除Cookie
		long validTimeInCookie = new Long(cookieValues[1]);
		if (validTimeInCookie < System.currentTimeMillis()) {
			// 删除Cookie
			clearCookie(response);
			return -3;
		}
		// 取出cookie中的用户名,并到数据库中检查这个用户名,
		String userName = cookieValues[0];

		//User userInfo = userDao.findUserByName(userName);// ud.selectUserByUsername(username);
		//调用 统一认证
		//DbContextHolder.setDbType(DataSourceConst.SLAVE); //调用service之前只需要设置上下文 调用相应的数据源	
		User userInfo = userService.findUserByName(userName);					
		//DbContextHolder.clearDbType();
		
		// 如果user返回不为空,就取出密码,使用用户名+密码+有效时间+ webSiteKey进行MD5加密
		if (userInfo != null) {
			String md5ValueInCookie = cookieValues[2];
			String md5ValueFromUser = getMD5(userInfo.getUserName() + ":"+ userInfo.getPassword() + ":" + validTimeInCookie + ":"+ Constants.WEB_KEY);
			
			
			// 将结果与Cookie中的MD5码相比较,如果相同,写入Session,自动登陆成功,并继续用户请求
			if (md5ValueFromUser.equals(md5ValueInCookie)) {
				HttpSession session = request.getSession(true);
				session.setAttribute("userInfo", userInfo);
				return userInfo.getId();//成功
			}
		} else {
			return -4;
		}
		return -5;
	}

	// 用户注销时,清除Cookie,在需要时可随时调用------------------------------------------------------------
	public void clearCookie(HttpServletResponse response) {
		Cookie cookie = new Cookie(Constants.COOKIE_DOMAIN_NAME, null);
		cookie.setMaxAge(0);
		cookie.setPath("/");
		response.addCookie(cookie);
	}

	// 获取Cookie组合字符串的MD5码的字符串----------------------------------------------------------------------------
	public String getMD5(String value) {
		String result = null;
		try {
			byte[] valueByte = value.getBytes();
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(valueByte);
			result = toHex(md.digest());
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return result;
	}

	// 将传递进来的字节数组转换成十六进制的字符串形式并返回
	private String toHex(byte[] buffer) {
		StringBuffer sb = new StringBuffer(buffer.length * 2);
		for (int i = 0; i < buffer.length; i++) {
			sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));
			sb.append(Character.forDigit(buffer[i] & 0x0f, 16));
		}
		return sb.toString();
	}
}